package auth

import (
	"context"

	"gitee.com/go-course/go9/projects/devcloud/mcenter/apps/service"
	"github.com/infraboard/mcube/app"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
)

func NewGrpcAuther() *grpcAuther {
	return &grpcAuther{
		service: app.GetInternalApp(service.AppName).(service.ServiceManager),
	}
}

type grpcAuther struct {
	service service.ServiceManager
}

func (a *grpcAuther) GetClientCredentialsFromMeta(md metadata.MD) (
	clientId, clientSecret string) {
	cids := md.Get(service.ClientHeaderKey)
	sids := md.Get(service.ClientSecretKey)
	if len(cids) > 0 {
		clientId = cids[0]
	}
	if len(sids) > 0 {
		clientSecret = sids[0]
	}
	return
}

// GRPC 服务端Auth中间件
// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
// to complete the RPC.
func (a *grpcAuther) AuthFunc(
	ctx context.Context,
	req interface{},
	info *grpc.UnaryServerInfo,
	handler grpc.UnaryHandler,
) (
	resp interface{}, err error) {
	// 获取客户端端凭证, 也放置Header(meta), meta存放在ctx中
	md, ok := metadata.FromIncomingContext(ctx)
	if !ok {
		return nil, status.Error(codes.PermissionDenied, "需要认证")
	}

	clientId, clientSecret := a.GetClientCredentialsFromMeta(md)
	if clientId == "" || clientSecret == "" {

		return nil, status.Error(codes.PermissionDenied, "需要认证")
	}
	svc, err := a.service.DescribeService(ctx, &service.DescribeServiceRequest{
		DescribeBy:    service.DESCRIBE_BY_SERVICE_CREDENTAIL_ID,
		DescribeVaule: clientId,
	})
	if err != nil {
		return nil, status.Errorf(codes.PermissionDenied, "认证异常: %s", err)
	}

	if clientSecret != svc.Credentail.ClientSecret {
		return nil, status.Error(codes.PermissionDenied, "认证失败")
	}

	resp, err = handler(ctx, req)

	// 处理响应后数据
	return resp, err
}
